package com.avanty.activiti;

import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class DeployActiviti implements ApplicationRunner {

	/**
	 * 流程部署相关表 `ACT_RE_DEPLOYMENT` `ACT_RE_MODEL` `ACT_GE_BYTEARRAY`
	 * `ACT_GE_PROPERTY` `ACT_RE_PROCDEF`
	 */

	/**
	 * 流程运行相关表 `ACT_RU_EXECUTION` `ACT_RU_IDENTITYLINK` `ACT_RU_JOB` `ACT_RU_TASK`
	 * `ACT_RU_VARIABLE`
	 */

	/**
	 * 流程历史相关表 `ACT_HI_IDENTITYLINK` `ACT_HI_VARINST` `ACT_HI_ACTINST`
	 * `ACT_HI_TASKINST`
	 */

	/**
	 * TaskQuery taskQuery = taskService.createTaskQuery();
	 * taskQuery.taskCandidateGroupIn(roleList);
	 * taskQuery.taskCandidateOrAssigned(usrnames);
	 * taskQuery.includeProcessVariables(); taskList = taskQuery.list();
	 */

	@Autowired
	ProcessEngine processEngine;

	@Autowired
	RuntimeService runtimeService;

	@Autowired
	TaskService taskService;

	@Autowired
	HistoryService historyService;

	@Autowired
	RepositoryService repositoryService;

	@Override
	public void run(ApplicationArguments args) {
		deployProcess();
	}

	private void deployProcess() {
		RepositoryService service = processEngine.getRepositoryService();
		InputStream bpmn = this.getClass().getResourceAsStream("/activiti/Process.bpmn");
		Deployment deployment = service.createDeployment().name("任务流程").addInputStream("Process.bpmn", bpmn).deploy();
		System.out.println(deployment.getName());
		System.out.println(deployment.getId());
	}

	/**
	 * 发起任务
	 */
	private void step1() {
		String processInstanceByKey = "Process";
		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processInstanceByKey);
		System.out.println(processInstance.getId());
	}

	/**
	 * 查看发起任务
	 */
	private void findStep1() {
		TaskQuery taskQuery = taskService.createTaskQuery();
		List<String> roleCodeList = new ArrayList<>();
		roleCodeList.add("user1");
		taskQuery.taskCandidateGroupIn(roleCodeList);
		taskQuery.includeProcessVariables();
		List<Task> tasks = taskQuery.list();
		for (Task task : tasks) {
			System.out.println(task.getId());
			System.out.println(task.getProcessInstanceId());
			System.out.println(task.getName());
		}
	}

	/**
	 * 分发任务
	 */
	private void step2() {
		TaskQuery taskQuery = taskService.createTaskQuery();
		List<String> roleCodeList = new ArrayList<>();
		roleCodeList.add("user1");
		taskQuery.taskCandidateGroupIn(roleCodeList);
		taskQuery.includeProcessVariables();
		Task task = taskQuery.singleResult();

		Map<String, Object> variables = new HashMap<>();
		List<String> users = new ArrayList<>();
		users.add("Michael");
		users.add("Zhan");
		variables.put("users", users);
		taskService.complete(task.getId(), variables);
		System.out.println("finish");
	}

	/**
	 * 查看分发任务
	 */
	private void findStep2() {
		String assignee = "Zhan";
		// String assignee = "Michael";
		List<Task> tasks1 = taskService.createTaskQuery().taskCandidateUser(assignee).list();
		for (Task task1 : tasks1) {
			System.out.println(task1.getId());
			System.out.println(task1.getName());
		}
	}

	/**
	 * 子流程-执行任务
	 */
	private void step3() {
		TaskQuery taskQuery = taskService.createTaskQuery();
		taskQuery.taskCandidateOrAssigned("Michael");
		taskQuery.includeProcessVariables();
		Task task = taskQuery.singleResult();
		System.out.println(task.getId());
		Map<String, Object> variables = new HashMap<>();
		List<String> users = new ArrayList<>();
		users.add("admin");
		users.add("root");
		variables.put("users", users);
		variables.put("isPass", 1);
		taskService.complete(task.getId(), variables);
		System.out.println("finish");
	}

	/**
	 * 子流程-查看执行任务
	 */
	private void findStep3() {
		String assignee = "admin";
		// String assignee = "root";
		List<Task> tasks = taskService.createTaskQuery().taskCandidateOrAssigned(assignee).list();
		for (Task task : tasks) {
			System.out.println(task.getId());
			System.out.println(task.getProcessInstanceId());
			System.out.println(task.getName());
		}
	}

	/**
	 * 子流程-验收任务
	 */
	private void step4() {
		String assignee = "admin";
		Task task = taskService.createTaskQuery().taskCandidateOrAssigned(assignee).singleResult();
		System.out.println(task.getId());
		Map<String, Object> variables = new HashMap<>();
		List<String> users = new ArrayList<>();
		if (assignee.equals("root")) {
			users.add("administrator");
			users.add("su");
		} else if (assignee.equals("admin")) {
			users.add("alex");
			users.add("sudo");
		}
		variables.put("users", users);
		taskService.complete(task.getId(), variables);
		System.out.println("finish");
	}

	/**
	 * 子流程-查看验收任务
	 */
	private void findStep4() {
		// String assignee = "administrator";
		// String assignee = "su";
		// String assignee = "alex";
		String assignee = "sudo";
		List<Task> tasks = taskService.createTaskQuery().taskCandidateOrAssigned(assignee).list();
		for (Task task : tasks) {
			System.out.println(task.getId());
			System.out.println(task.getProcessInstanceId());
			System.out.println(task.getName());
		}
	}

	/**
	 * 子流程-完成
	 */
	private void finish() {
		String assignee = "alex";
		Task task = taskService.createTaskQuery().taskCandidateOrAssigned(assignee).singleResult();
		Map<String, Object> variables = new HashMap<>();
		variables.put("isPass", 1);
		taskService.complete(task.getId(), variables);
		System.out.println("finish");
	}

	/**
	 * 撤回流程
	 */
	private void recall() {
		List<String> roleCodeList = new ArrayList<>();
		roleCodeList.add("user1");
		// 取得已提交的任务
		HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
				.taskCandidateGroupIn(roleCodeList).singleResult();
		// HistoricTaskInstance historicTaskInstance =
		// historyService.createHistoricTaskInstanceQuery().taskAssignee(assignee).singleResult();
		// HistoricTaskInstance historicTaskInstance =
		// historyService.createHistoricTaskInstanceQuery().taskCandidateUser(assignee).singleResult();
		System.out.println(historicTaskInstance.getId());
		// 取得流程实例
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
				.processInstanceId(historicTaskInstance.getProcessInstanceId()).singleResult();
		System.out.println(processInstance.getId());
		Map<String, Object> variables = runtimeService.getVariables(historicTaskInstance.getExecutionId());
		System.out.println(variables);
		// 取得流程定义
		ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity) repositoryService
				.getProcessDefinition(historicTaskInstance.getProcessDefinitionId());
		System.out.println(definitionEntity);
		// 取得上一步活动
		ActivityImpl hisActivity = definitionEntity.findActivity(historicTaskInstance.getTaskDefinitionKey());
		System.out.println(hisActivity);
		// 取得当前活动
		List<PvmTransition> currTransitionList = hisActivity.getOutgoingTransitions();
		System.out.println(currTransitionList);

		for (PvmTransition currTransition : currTransitionList) {
			PvmActivity currActivity = currTransition.getDestination();
			List<Task> currTasks = taskService.createTaskQuery().processInstanceId(processInstance.getId())
					.taskDefinitionKey(currActivity.getId()).list();
			for (Task currTask : currTasks) {
				ArrayList<PvmTransition> oriPvmTransitionList = new ArrayList<>();
				List<PvmTransition> pvmTransitionList = currActivity.getOutgoingTransitions();
				System.out.println(pvmTransitionList);
				for (PvmTransition pvmTransition : pvmTransitionList) {
					oriPvmTransitionList.add(pvmTransition);
				}
				System.out.println(oriPvmTransitionList);
				pvmTransitionList.clear();
				// 建立新方向
				ActivityImpl nextActivityImpl = ((ProcessDefinitionImpl) definitionEntity)
						.findActivity(currActivity.getId());
				TransitionImpl newTransition = nextActivityImpl.createOutgoingTransition();
				newTransition.setDestination(hisActivity);
				taskService.claim(currTask.getId(), null);
				taskService.complete(currTask.getId(), variables);
				historyService.deleteHistoricTaskInstance(currTask.getId());

				// 恢复方向
				hisActivity.getIncomingTransitions().remove(newTransition);
				List<PvmTransition> pvmTList = currActivity.getOutgoingTransitions();
				pvmTList.clear();
				for (PvmTransition pvmTransition : oriPvmTransitionList) {
					pvmTransitionList.add(pvmTransition);
				}
				System.out.println(pvmTransitionList);
			}
		}
		historyService.deleteHistoricTaskInstance(historicTaskInstance.getId());
	}

}
